package account

import (
	"context"
	"crypto/md5"
	"demo/api/backend/system/account"
	"demo/internal/consts"
	"demo/internal/dao"
	"demo/internal/model/do"
	"demo/internal/model/entity"
	"demo/internal/service"
	"demo/library/liberr"
	"encoding/hex"
	"fmt"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"reflect"
)

func init() {
	fmt.Print("login init")
	service.RegisterAccount(New())
}
func New() *sAccount {
	return &sAccount{}
}

type sAccount struct {
}

func (s *sAccount) GetList(ctx context.Context) (total interface{}, userList []*entity.Account, err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		m := dao.Account.Ctx(ctx)
		total, err = m.Count()
		if err != nil {
			panic("查询数量失败")
		}
		err = m.FieldsEx(dao.Account.Columns().LoginPwd).Order("account_id asc").Scan(&userList)
		if err != nil {
			panic("查询结果失败")
		}
	})
	return
}

func (s *sAccount) Add(ctx context.Context, req *account.AddReq) error {
	err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		err := g.Try(ctx, func(ctx context.Context) {
			var accountLog *entity.Account
			err := dao.Account.Ctx(ctx).Where(dao.Account.Columns().LoginName, req.Email).Scan(&accountLog)
			liberr.ErrIsNil(ctx, err, "查询异常")
			liberr.ValueNotIsNil(accountLog, "当前账号已存在")
			password, err := s.GenAccountPassword(ctx, "123456")
			liberr.ErrIsNil(ctx, err, "生成密码失败")
			accountId, err := dao.Account.Ctx(ctx).TX(tx).InsertAndGetId(do.Account{
				AccountName:        req.AccountName,
				EnName:             req.EnName,
				LoginPwd:           password,
				LoginName:          req.Email,
				Email:              req.Email,
				Sex:                req.Sex,
				Address:            req.Address,
				DepartmentIdentity: req.DepartmentIdentity,
				Phone:              req.Phone,
			})
			liberr.ErrIsNil(ctx, err, "新增用户信息失败")
			//设置用户所属角色信息
			//程序支持多个角色
			var roleIds = []int{req.RoleId}
			err = s.EditAccountRole(ctx, roleIds, gconv.Int(accountId))
			liberr.ErrIsNil(ctx, err, "设置用户角色失败")
			err = s.EditAccountDep(ctx, req.DepartmentIds, gconv.Int(accountId))
			liberr.ErrIsNil(ctx, err, "设置用户部门失败")
		})
		return err
	})

	return err
}

func (s *sAccount) Update(ctx context.Context, req *account.UpdateReq) error {

	err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		err := g.Try(ctx, func(ctx context.Context) {
			_, err := dao.Account.Ctx(ctx).TX(tx).WherePri(req.AccountId).Update(do.Account{
				AccountName:        req.AccountName,
				EnName:             req.EnName,
				Sex:                req.Sex,
				Address:            req.Address,
				DepartmentIdentity: req.DepartmentIdentity,
				Phone:              req.Phone,
			})
			liberr.ErrIsNil(ctx, err, "修改用户信息失败")
			//设置用户所属角色信息
			//程序支持多个角色
			var roleIds = []int{req.RoleId}
			err = s.EditAccountRole(ctx, roleIds, req.AccountId)
			liberr.ErrIsNil(ctx, err, "设置用户角色失败")
			err = s.EditAccountDep(ctx, req.DepartmentIds, req.AccountId)
			liberr.ErrIsNil(ctx, err, "设置用户部门失败")
		})
		return err
	})
	return err
}

func (s *sAccount) Sate(ctx context.Context, req *account.SateReq) error {
	_, err := dao.Account.Ctx(ctx).Where(dao.Account.Columns().AccountId, req.AccountId).Update(do.Account{
		State: req.State,
	})
	return err
}

func (s *sAccount) EditAccountRole(ctx context.Context, roleIds []int, accountId int) error {
	err := g.Try(ctx, func(ctx context.Context) {
		var existRoles []*entity.AccountRoles
		err := dao.AccountRoles.Ctx(ctx).Where(dao.AccountRoles.Columns().AccountId, accountId).Scan(&existRoles)
		liberr.ErrIsNil(ctx, err, "角色查找失败")

		var currentRoleIds []int
		for _, role := range existRoles {
			currentRoleIds = append(currentRoleIds, role.RoleId)
		}
		// 比较并更新
		if !reflect.DeepEqual(currentRoleIds, roleIds) {
			// 删除操作
			_, err = dao.AccountRoles.Ctx(ctx).Where(dao.AccountRoles.Columns().AccountId, accountId).Delete()
			liberr.ErrIsNil(ctx, err, "角色删除失败")
			// 重新更新
			var accountRoles []entity.AccountRoles
			for _, roleId := range roleIds {
				accountRoles = append(accountRoles, entity.AccountRoles{
					AccountId: accountId,
					RoleId:    roleId,
				})
			}
			_, err = dao.AccountRoles.Ctx(ctx).Data(accountRoles).Insert()
			if err != nil {
				liberr.ErrIsNil(ctx, err, "角色插入失败")
			}
		}
	})
	return err
}

func (s *sAccount) EditAccountDep(ctx context.Context, depIds []int, accountId int) error {
	err := g.Try(ctx, func(ctx context.Context) {
		var existDeps []*entity.AccountDepartment
		err := dao.AccountDepartment.Ctx(ctx).Where(dao.AccountDepartment.Columns().AccountId, accountId).Scan(&existDeps)
		liberr.ErrIsNil(ctx, err, "部门查找失败")

		var currentDepIds []int
		for _, dep := range existDeps {
			currentDepIds = append(currentDepIds, dep.DepartmentId)
		}
		// 比较并更新
		if !reflect.DeepEqual(currentDepIds, depIds) {
			// 删除操作
			_, err = dao.AccountDepartment.Ctx(ctx).Where(dao.AccountDepartment.Columns().AccountId, accountId).Delete()
			liberr.ErrIsNil(ctx, err, "部门删除失败")
			// 重新更新
			var accountDeps []entity.AccountDepartment
			for _, depId := range depIds {
				accountDeps = append(accountDeps, entity.AccountDepartment{
					AccountId:    accountId,
					DepartmentId: depId,
				})
			}
			_, err = dao.AccountDepartment.Ctx(ctx).Data(accountDeps).Insert()
			if err != nil {
				liberr.ErrIsNil(ctx, err, "部门插入失败")
			}
		}
	})
	return err
}

func (s *sAccount) GenAccountPassword(ctx context.Context, password string) (newPassword string, err error) {

	hashedBytes := md5.Sum([]byte(password + consts.PasswordSalt))
	return hex.EncodeToString(hashedBytes[:]), nil

}
